package com.ymt.fmd.platform.service;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.ibatis.javassist.expr.NewArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ymt.fmd.platform.dao.mysql.CustomSQLDao;
import com.ymt.fmd.platform.dao.mysql.PI18nMapper;
import com.ymt.fmd.platform.model.PI18n;
import com.ymt.fmd.platform.service.MetadataService;
import com.ymt.fmd.util.Const;
import com.ymt.fmd.util.DhxUtil;
import com.ymt.fmd.util.MetaDataUtil;

/**
 * Service for operate meta data
 * @author fuzheng
 *
 */
@Service
public class MetadataService {
	
	/**
	 * Logger
	 */
	private static Logger logger = Logger.getLogger(MetadataService.class.getName());
	/**
	 * CustomSQLDao
	 */
	@Autowired
	private CustomSQLDao csDao;
	/**
	 * PI18nMapper
	 */
	@Autowired
	private PI18nMapper iDao;
	/**
	 * PServiceService
	 */
	@Autowired
	private PServiceService ss;
	
	/**
	 * Get enumeration types in i18n table
	 * @return
	 */
	public String getEnumerationTypes(String tenantId) {
		List<Map<String,?>> list = iDao.getI18nTypesByCategory(tenantId, MetaDataUtil.I18N_CATEGORY_ENUM);
		JSONObject rtn = new JSONObject();
		JSONArray rows = new JSONArray();
		for (int i=0; i<list.size(); i++) {
			JSONArray data = new JSONArray();
			data.add(i+1);
			data.add(list.get(i).get("TYPEKEY"));
			data.add(list.get(i).get("TARGET"));
			data.add(list.get(i).get("CATEGORY"));
			JSONObject row = new JSONObject();
			row.put(DhxUtil.ID, i+1);
			row.put(DhxUtil.DATA, data);
			rows.add(row);
		}
		rtn.put(DhxUtil.ROWS, rows);
		return rtn.toString();
	}
	
	/**
	 * Get enumeration values in i18n table
	 * @param type
	 * @return
	 */
	public String getEnumerationValues(String tenantId, String type, String target) {
		
		PI18n obj = new PI18n();
		obj.setTenantId(tenantId);
		obj.setTarget(target);
		obj.setCategory(MetaDataUtil.I18N_CATEGORY_ENUM);
		obj.setType(type);
		List<PI18n> list = iDao.selectByObject(obj);
		logger.finest("getEnumerationValues list.size()="+list.size());
		
		JSONObject rtn = new JSONObject();
		JSONArray rows = new JSONArray();
		for (int i=0; i<list.size(); i++) {
			JSONArray data = new JSONArray();
			data.add(i+1);
			data.add(list.get(i).getRelationkey());
			data.add(list.get(i).getLang());
			data.add(list.get(i).getValue());
			JSONObject row = new JSONObject();
			row.put(DhxUtil.ID, i);
			row.put(DhxUtil.DATA, data);
			rows.add(row);
		}
		rtn.put(DhxUtil.ROWS, rows);
		return rtn.toString();
	}
	
	/**
	 * Get enumerations
	 * @param lang
	 * @param typeList
	 * @return
	 */
	public String getEnumerations(String tenantId, String lang, String typeList) {
		JSONArray list = JSONArray.parseArray(typeList);
		JSONObject rtn = new JSONObject();
		for (int i=0; i<list.size(); i++) {
			JSONObject obj = list.getJSONObject(i);
			String type = obj.getString("type");
			String target = obj.getString("target");
			String data = getEnumerationValuesByLang2(tenantId, lang, type, target);
			rtn.put(type, data);
		}
		return rtn.toString();
	}
	
	/**
	 * Get enumeration values in i18n table
	 * @param type
	 * @return
	 */
	public String getEnumerationValuesByLang(String tenantId, String lang, String type, String target) {
		
		PI18n obj = new PI18n();
		obj.setTenantId(tenantId);
		obj.setTarget(target);
		obj.setCategory(MetaDataUtil.I18N_CATEGORY_ENUM);
		obj.setType(type);
		obj.setLang(lang);
		List<PI18n> list = iDao.selectByObject(obj);
		logger.finest("getEnumerationValues list.size()="+list.size());
		
		JSONObject rtn = new JSONObject();
		JSONArray rows = new JSONArray();
		for (int i=0; i<list.size(); i++) {
			JSONArray data = new JSONArray();
			data.add(i+1);
			data.add(list.get(i).getRelationkey());
			data.add(list.get(i).getLang());
			data.add(list.get(i).getValue());
			JSONObject row = new JSONObject();
			row.put(DhxUtil.ID, i);
			row.put(DhxUtil.DATA, data);
			rows.add(row);
		}
		rtn.put(DhxUtil.ROWS, rows);
		return rtn.toString();
	}
	
	/**
	 * Get enumeration values in i18n table
	 * @param type
	 * @return
	 */
	public String getEnumerationValuesByLang2(String tenantId, String lang, String type, String target) {
		PI18n obj = new PI18n();
		obj.setTenantId(tenantId);
		obj.setTarget(target);
		obj.setCategory(MetaDataUtil.I18N_CATEGORY_ENUM);
		obj.setType(type);
		obj.setLang(lang);
		List<PI18n> list = iDao.selectByObject(obj);
		logger.finest("getEnumerationValuesByLang2 list.size()="+list.size());
		
		JSONArray rtn = new JSONArray();
		for (int i=0; i<list.size(); i++) {
			JSONArray data = new JSONArray();
			data.add(list.get(i).getRelationkey());
			data.add(list.get(i).getValue());
			rtn.add(data);
		}
		return rtn.toString();
	}
	
	
	/**
	 * Save data in P_I18N
	 * @param values
	 */
	public void saveI18N(String tenantId, String values) {
		logger.finest("saveI18N values="+values);
		JSONArray vala = JSONArray.parseArray(values);
		for (int i=0; i<vala.size(); i++) {
			JSONObject vals = vala.getJSONObject(i);
			String type = vals.getString("type").toUpperCase();//save to upper case
			String value = vals.getString("value");
			String target = vals.getString("target");
			for (String l : new String[]{Const.LANG_ZH, Const.LANG_EN}) {
				
				PI18n i18n = new PI18n();
				i18n.setTenantId(tenantId);
				i18n.setTarget(target);
				i18n.setCategory(MetaDataUtil.I18N_CATEGORY_ENUM);
				i18n.setType(type);
				i18n.setLang(l);
				i18n.setRelationkey(value);
				i18n.setValue(vals.getString(l));
				String sort = String.valueOf(iDao.getMaxSortByType(i18n).get("MAX"));
				i18n.setSort(sort);
				iDao.insert(i18n);
			}
		}
	}
	
	/**
	 * Delete data in P_I18N
	 * @param condition
	 */
	public void deleteI18N(String tenantId, String condition) {
		String sql = "DELETE FROM P_I18N WHERE "+condition;
		if (tenantId!=null) {
			sql += " AND TENANT_ID="+tenantId;
		}
		logger.finest("deleteI18N sql="+sql);
		csDao.delete(sql);
	}
	
	/**
	 * reorder i18n
	 * @param category
	 * @param target
	 * @param type
	 * @param orders
	 */
	public void reorderI18N(String tenantId, String category, String target, String type, String orders) {
		JSONArray ja = JSONArray.parseArray(orders);
		for (int i=0; i<ja.size(); i++) {
			iDao.updateSort(tenantId, category, target, type, ja.getString(i), String.valueOf(i+1));
		}
	}
	
	/**
	 * Query
	 */
	@SuppressWarnings("unchecked")
	public String queryDict(String tenantId, String args, String orders, String lang, int fInd, int lInd, int timezoneOffset) {
		logger.finer("queryDict args="+args);
		Map<String, Object> params = new HashMap<String,Object>();
		Map<String, Object> bo = new HashMap<String,Object>();
		if (tenantId!=null) {
			bo.put("tenantId", tenantId);
		}
		if (args!=null) {
			bo.putAll(JSONObject.parseObject(args));
			bo.put(Const.LANG, lang);
			if (!bo.containsKey("target")) {
				bo.put("target", "BPM");
			}
			if (!bo.containsKey("category")) {
				bo.put("category", "ENUMERATION");
			}
		}
		params.put("bo", bo);
		params.put("fromRow", fInd-1);
		params.put("toRow", lInd);
		params.put("rows", lInd - fInd + 1);
		params.put("orderby", DhxUtil.parseGridOrderBy(orders));
		logger.finer("query params="+params);
		List<Map<String,?>> list = iDao.pagingSelect(params);
		int total = Integer.parseInt(iDao.pagingSelectCount(params).get("COUNT").toString());
		String[] cols = new String[]{"TYPE","TYPEDESC"};
		String rtn= DhxUtil.toGridJsonStr(list, 
				cols, fInd, total, timezoneOffset, lang);
		logger.finer("queryDict returns:\n"+rtn);
		return rtn;
	}
	
	/**
	 * get enumerations for dataproviders
	 * @param dpStr
	 * @param lang
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	public String getEnumerationsForDp(String tenantId, String dpStr, String lang) throws UnsupportedEncodingException {
		JSONObject dpsJo = JSONObject.parseObject(dpStr);
		JSONObject rtn = new JSONObject();
		for (Object key : dpsJo.keySet()) {
			String eid = (String)key;
			JSONObject dpJo = dpsJo.getJSONObject(eid);
			if (!"enu".equalsIgnoreCase(dpJo.getString("rtn"))) {//必须返回枚举类型
				continue;
			}
			String dp = dpJo.getString("dp");
			if (dp==null) {
				continue;
			}
			String enuarr = null;
			if ("dict".equalsIgnoreCase(dp)) {
				enuarr = getEnumerationValuesByLang2(tenantId, lang, dpJo.getString("type"), dpJo.getString("target"));
			} else if ("svc".equalsIgnoreCase(dp)) {
				String svcId = dpJo.getString("svcid");
				JSONArray intfvars = dpJo.getJSONArray("intfvars");
				enuarr = ss.callRestService(svcId, intfvars);
			}
			if (enuarr!=null) {
				rtn.put(eid, JSONArray.parseArray(enuarr));
			}
		}
		return rtn.toString();
	}
	
	/**
	 * Get enumeration values in i18n table
	 * @param type
	 * @return
	 */
	public String getEnumerationValuesForTreeGrid(String tenantId, String type, String target) {
		
		PI18n obj = new PI18n();
		obj.setTenantId(tenantId);
		obj.setTarget(target);
		obj.setCategory(MetaDataUtil.I18N_CATEGORY_ENUM);
		obj.setType(type);
		List<PI18n> list = iDao.selectByObject(obj);
		logger.finest("getEnumerationValues list.size()="+list.size());
		
		JSONObject rtn = new JSONObject();
		JSONArray rows = new JSONArray();
		String relationKey = "";
		int rowid = 1;
		int no = 1;
		int i=0;
		while ( i<list.size()) {
			if (!list.get(i).getRelationkey().equals(relationKey)) {
				//add new row
				JSONArray data = new JSONArray();
				data.add(no++);
				data.add(list.get(i).getRelationkey());
				data.add("");
				data.add("");
				JSONObject row = new JSONObject();
				row.put(DhxUtil.ID, rowid++);
				row.put(DhxUtil.DATA, data);
				row.put(DhxUtil.ROWS, new JSONArray());
				rows.add(row);
				relationKey = list.get(i).getRelationkey();
			} else {
				//add new sub row
				JSONArray data = new JSONArray();
				data.add("");
				data.add(list.get(i).getRelationkey());
				data.add(list.get(i).getLang());
				data.add(list.get(i).getValue());
				JSONObject row = new JSONObject();
				row.put(DhxUtil.ID, rowid++);
				row.put(DhxUtil.DATA, data);
				//add row to sub list of last row
				int last = rows.size()-1;
				if (rows.getJSONObject(last).getJSONArray(DhxUtil.ROWS)==null) {
					rows.getJSONObject(last).put(DhxUtil.ROWS, new JSONArray());
				}
				rows.getJSONObject(last).getJSONArray(DhxUtil.ROWS).add(row);
				i++;
			}
		}
		rtn.put(DhxUtil.ROWS, rows);
		return rtn.toString();
	}
	
}
